﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Demo.Framework.Event
{
    class Program
    {
        static void Main(string[] args)
        {
            // client
            try
            {
                Server s = new Server();
                s.ServerEvent += new Server.ServerEventHandler(s_ServerEvent);

                System.Threading.Thread.Sleep(3000);
                s.RaiseEvent();

                // Test for - What happens if an event is raised and the event
                //is meant to be subscribed in multiple handlers

                // When an event is subscribed by multiple subscribers, the 
                // execution goes to multiple subscribers in sequence

                var e = new EventProcessor();

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
            finally
            {
                Console.Read();
            }
        }

        static void s_ServerEvent(object sender, ServerEventAgrs e)
        {
            Console.WriteLine("Received Server Event. Server State {0}", e.ServerState.ToString());
        }
    }

    public class Server
    {
        public delegate void ServerEventHandler(object sender, ServerEventAgrs e);
        public event ServerEventHandler ServerEvent;
        public Server()
        { }

        public void RaiseEvent()
        {
            // raise event
            ServerEvent(this, new ServerEventAgrs(new ServerState(1, 2)));
        }
    }

    public class ServerEventAgrs : EventArgs
    {
        public ServerState ServerState { get; set; }

        public ServerEventAgrs(ServerState state)
        {
            ServerState = state;
        }
    }

    public class ServerState
    {
        public ServerState(int i, int j)
        {
            this.Prop1 = i;
            this.Prop2 = j;
        }

        public int Prop1 { get; set; }
        public int Prop2 { get; set; }

        public override string ToString()
        {
            return (Prop1 + Prop2).ToString();
        }
    }

    public class EventProcessor
    {
        public EventProcessor()
        {
            Server s = new Server();
            s.ServerEvent += new Server.ServerEventHandler(HandleEvent_1);
            s.RaiseEvent(); 
            s.ServerEvent += new Server.ServerEventHandler(HandleEvent_2);
            s.ServerEvent += new Server.ServerEventHandler(HandleEvent_3);
            s.RaiseEvent();                        

            // This is not possible, Events can only be risen from inside the class.
            // If you could do that, it would defeat the purpose of events
            // (being able to rise status changes from inside the class).           

            //s.ServerEvent(this, new ServerEventAgrs(new ServerState(1,2)));

            // MSDN
            // Events are a special kind of multicast delegate that can only be invoked from within the class
            // or struct where they are declared (the publisher class). If other classes or structs subscribe
            // to the event, their event handler methods will be called when the publisher class raises the event

            //Events can be marked as public, private, protected, internal, or protected internal. 
        }

        public void HandleEvent_1(object sender, ServerEventAgrs e)
        {            
            Console.WriteLine("Event Handler 1");
        }

        public void HandleEvent_2(object sender, ServerEventAgrs e)
        {
            Console.WriteLine("Event Handler 2");
        }

        public void HandleEvent_3(object sender, ServerEventAgrs e)
        {
            Console.WriteLine("Event Handler 3");
        }
    }
}
